package Agent;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import Agent.Util;
import Perception.Percepts;
import Perception.PerceptsBase;
import Perception.Parameter;
import Goal.GoalBase;
import jade.core.behaviours.Behaviour;

public class ConnexionBehaviour extends Behaviour {

	int step;
	
	private PerceptsBase percepts;
	private GoalBase goals;
	private Connexion con;
	private String role;
	
	public ConnexionBehaviour(PerceptsBase percepts,Connexion con, GoalBase goals,String role)
	{
		step = 0;
		this.percepts = percepts;
		this.role = role;
		this.con = con;
		this.goals = goals;
	}
	
	@Override
	public void action() 
	{
		switch(step)
		{
			case 0 :
			{
				System.out.println("Connexion init");
				while(!con.isConnected())
					con.connect();
				step++;
			}
			case 1 :
			{
				boolean actionToDo = false;
				while(!actionToDo)
				{
					try {
						actionToDo = checkRequest(con.receiveDoc());
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						System.out.println("Probleme message reçu");
					}
				}
				((AgentBase)getAgent()).actionOK = false;
				
			}
			break;
			default :
		}
	}
	
	public boolean checkRequest(Document doc)
	{	
		if(doc == null)
			return false;
		else
		{
			Element root = (Element) doc.getDocumentElement();
			String type = root.getAttribute("type");
						
			if ( type.equalsIgnoreCase("sim-start") ) {
				
				
					((AgentBase)getAgent()).initAttr();
					NodeList tags = root.getElementsByTagName("simulation");
					checkPerceptSimStart(doc);
					Element tag = (Element) tags.item(0);
					String str = tag.getAttribute("role");
					if(!str.equals(role))
					{
						getAgent().doDelete();
						System.out.println("Erreur Role : "+role+" attendu "+str);
						return true;
					}
					return false;
						
			}
			else if ( type.equalsIgnoreCase("request-action") ) {
				String str = null;
				NodeList tags = root.getElementsByTagName("perception");
				assert tags.getLength() == 1;
				Element tag = (Element) tags.item(0);
				str = tag.getAttribute("id");
				assert str != null && str.equals("") == false;
				
				int id = Integer.parseInt(str);
				checkPerceptActionRequest(doc);
				
				/*if(agent.isVerbose())
					System.out.println("Id action : "+id);
				/*
				if(agent.getCurrentId()  == (id-1))
				{
					System.out.println("Erreur id action invalide");
				}
				 */
				con.setCurrentId(id);
				return true;
				
			}
			else if ( type.equalsIgnoreCase("sim-end") ) {

				checkPerceptSimEnd(doc);
				return false;
				
			}
			else if ( type.equalsIgnoreCase("bye") ) 
			{
				getAgent().doDelete();
				return true;
			}
			else 
			{
				System.out.println("Message de type inconnu");
				return false;
			}
		}
	}

	@Override
	public boolean done() {
		// TODO Auto-generated method stub
		return false;
	}
	
	
	public void checkPerceptSimStart(Document doc)
	{
		
			Element root = doc.getDocumentElement();
			String str = null;
			assert root != null;
			assert root.getAttribute("type").equalsIgnoreCase("sim-start");
			percepts.clear();
			goals.clear();
			Percepts sim = new Percepts("Sim-Info");
			
			Element simulation = (Element)root.getElementsByTagName("simulation").item(0);
			assert simulation.getNodeName().equalsIgnoreCase("simulation");
			
			str = simulation.getAttribute("id");
			assert str != null && str.equals("") == false;
			Parameter<String> p = new Parameter<String>("id", str);
			sim.addParam(p);
			
			str = simulation.getAttribute("steps");
			assert str != null && str.equals("") == false;
			p = new Parameter<String>("steps", str);
			sim.addParam(p);
			
			str = simulation.getAttribute("vertices");
			assert str != null && str.equals("") == false;
			p = new Parameter<String>("vertices", str);
			sim.addParam(p);
			
			str = simulation.getAttribute("edges");
			assert str != null && str.equals("") == false;
			p = new Parameter<String>("edges", str);
			sim.addParam(p);
			
			str = simulation.getAttribute("role");
			assert str != null && str.equals("") == false;
			p = new Parameter<String>("role", str);
			sim.addParam(p);
			
			percepts.addPercept(sim);
			
	}

	public void checkPerceptActionRequest(Document doc)
	{
		String str;
		Percepts per;
		Element root = doc.getDocumentElement();
		
		assert root != null;
		assert root.getAttribute("type").equalsIgnoreCase("request-action");
		
		percepts.clear();
		per = new Percepts("Sim-State");
		percepts.removePercepts("Sim-State");
		
		str = root.getAttribute("timestamp");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		long timestamp = new Long(str).longValue();
		per.addParam("timestamp", str);

		Element perception = (Element)root.getElementsByTagName("perception").item(0);
		assert perception.getNodeName().equalsIgnoreCase("perception");

		str = perception.getAttribute("deadline");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		long deadline = new Long(str).longValue();
		per.addParam("deadline",str);
		
		NodeList tags;
		Element tag;
		int step;
		
		tags = perception.getElementsByTagName("simulation");
		assert tags.getLength() == 1 : Util.XMLToString(doc);
		tag = (Element) tags.item(0);
		
		str = tag.getAttribute("step");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		step = new Integer(str).intValue();
		per.addParam("step",str);
		
		percepts.addPercept(per);
		
		percepts.removePercepts("state");
		per = new Percepts("state");
		
		tags = perception.getElementsByTagName("self");
		assert tags.getLength() == 1;
		tag = (Element) tags.item(0);
		str = tag.getAttribute("zoneScore");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("zoneScore",str);
		
		str = tag.getAttribute("energy");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("energy",str);
		
		str = tag.getAttribute("health");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("health",str);
		
		str = tag.getAttribute("lastAction");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("lastAction",str);
		
		str = tag.getAttribute("lastActionParam");
		assert str != null : Util.XMLToString(doc);
		per.addParam("lastActionParam",str);
		
		str = tag.getAttribute("lastActionResult");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("lastActionResult",str);
		
		str = tag.getAttribute("maxEnergy");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("maxEnergy",str);
		
		str = tag.getAttribute("maxEnergyDisabled");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("maxEnergyDisabled",str);
		
		str = tag.getAttribute("maxHealth");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("maxHealth",str);
		
		str = tag.getAttribute("position");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("position",str);
		
		str = tag.getAttribute("strength");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("strength",str);
		
		str = tag.getAttribute("visRange");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("visRange",str);
		
		percepts.addPercept(per);
		
		percepts.removePercepts("team");
		per = new Percepts("team");
		tags = perception.getElementsByTagName("team");
		assert tags.getLength() == 1;
		tag = (Element) tags.item(0);
		
		str = tag.getAttribute("money");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("money",str);
		
		str = tag.getAttribute("zonesScore");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("zoneScore",str);
		
		str = tag.getAttribute("lastStepScore");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("lastStepScore",str);
		
		str = tag.getAttribute("score");
		assert str != null && str.equals("") == false : Util.XMLToString(doc);
		per.addParam("score",str);
		
		percepts.addPercept(per);
		
		tags = perception.getElementsByTagName("visibleVertices");
		assert tags.getLength() == 1;
		
		tag = (Element)tags.item(0);
		tags = tag.getElementsByTagName("visibleVertex");
		percepts.removePercepts("visibleVertex");
		
		for ( int a = 0 ; a < tags.getLength() ; a ++ ) {
			
			per = new Percepts("visibleVertex");
			tag = (Element)tags.item(a);
			
			str = tag.getAttribute("name");
			assert str != null && str.equals("") == false : Util.XMLToString(doc);
			per.addParam("name",str);
			
			str = tag.getAttribute("team");
			assert str != null && str.equals("") == false : Util.XMLToString(doc);
			per.addParam("team",str);

			percepts.addPercept(per);
		}

		tags = perception.getElementsByTagName("visibleEdges");
		assert tags.getLength() == 1;
		
		tag = (Element)tags.item(0);
		tags = tag.getElementsByTagName("visibleEdge");
		percepts.removePercepts("visibleEdge");
		
		for ( int a = 0 ; a < tags.getLength() ; a ++ ) {
			
			per = new Percepts("visibleEdge");
			tag = (Element)tags.item(a);
			
			str = tag.getAttribute("node1");
			assert str != null && str.equals("") == false : Util.XMLToString(tag);
			per.addParam("node1",str);
			
			str = tag.getAttribute("node2");
			assert str != null && str.equals("") == false : Util.XMLToString(tag);
			per.addParam("node2",str);			
			Percepts p = new Percepts("visibleEdge");

			percepts.addPercept(per);
		}
		
		// <visibleEntities>-tag and <visibleEntity>-tag
		tags = perception.getElementsByTagName("visibleEntities");
		percepts.removePercepts("visibleEntity");
		if ( tags.getLength() != 0 ) {
			tag = (Element)tags.item(0);
			tags = tag.getElementsByTagName("visibleEntity");
			for ( int a = 0 ; a < tags.getLength() ; a ++ ) {
				
				per = new Percepts("visibleEntity");
				
				tag = (Element)tags.item(a);
				str = tag.getAttribute("name");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("name",str);
				
				str = tag.getAttribute("node");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("node",str);
				
				str = tag.getAttribute("team");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("team",str);
				
				str = tag.getAttribute("status");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("status",str);
				
				percepts.addPercept(per);
			}
		}
		
		// <probedVertices>-tag and <probedVertex>-tag
		// <probedVertex name="vertex12" weight="8"/>
		tags = perception.getElementsByTagName("probedVertices");
		percepts.removePercepts("probedVertice");
		if ( tags.getLength() != 0 ) {
			tag = (Element)tags.item(0);
			tags = tag.getElementsByTagName("probedVertex");
			for ( int a = 0 ; a < tags.getLength() ; a ++ ) {
				
				per = new Percepts("probedVertex");
				tag = (Element)tags.item(a);
				
				str = tag.getAttribute("name");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("name",str);
				
				str = tag.getAttribute("value");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("value",str);
				
				percepts.addPercept(per);
			}
		}
		
		// <surveyedEdge node1="vertex12" node2="vertex19" weight="8"/>
		tags = perception.getElementsByTagName("surveyedEdges");
		percepts.removePercepts("surveyedEdge");
		if ( tags.getLength() != 0 ) {
			tag = (Element)tags.item(0);
			tags = tag.getElementsByTagName("surveyedEdge");
			for ( int a = 0 ; a < tags.getLength() ; a ++ ) {
				
				per = new Percepts("surveyedEdge");
				tag = (Element)tags.item(a);
				
				str = tag.getAttribute("node1");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("node1",str);
				
				str = tag.getAttribute("node2");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("node2",str);
				
				str = tag.getAttribute("weight");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("weight",str);
				
				percepts.addPercept(per);
			}
		}
		
		// <inspectedEntity energy="8" health="9" maxEnergy="8" maxHealth="9" name="b4" node="vertex9" strength="6" team="B" visRange="2"/>
		tags = perception.getElementsByTagName("inspectedEntities");
		percepts.removePercepts("inspectedEntity");
		
		if ( tags.getLength() != 0 ) {
			tag = (Element)tags.item(0);
			tags = tag.getElementsByTagName("inspectedEntity");
			for ( int a = 0 ; a < tags.getLength() ; a ++ ) {
				
				per = new Percepts("inspectedEntity");
				tag = (Element)tags.item(a);
			
				str = tag.getAttribute("name");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("name",str);
				
				str = tag.getAttribute("team");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("team",str);
				
				str = tag.getAttribute("role");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("role",str);
				
				str = tag.getAttribute("node");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("node",str);
				
				str = tag.getAttribute("energy");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("energy",str);
				
				str = tag.getAttribute("maxEnergy");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("maxEnergy",str);
				
				str = tag.getAttribute("health");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("health",str);
				
				str = tag.getAttribute("maxHealth");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("maxHealth",str);
				
				str = tag.getAttribute("strength");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("strength",str);
				
				str = tag.getAttribute("visRange");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("visRange",str);
				
				percepts.addPercept(per);
			}
		}

		// achievements
		tags = perception.getElementsByTagName("team");
		assert tags.getLength() == 1;
		tag = (Element) tags.item(0);
		
		percepts.removePercepts("achivement");
		tags = tag.getElementsByTagName("achievements");
		if ( tags.getLength() != 0 ) {
			tag = (Element)tags.item(0);
			tags = tag.getElementsByTagName("achievement");
			for ( int a = 0 ; a < tags.getLength() ; a ++ ) {
				
				per = new Percepts("achivement");
				tag = (Element)tags.item(a);
				str = tag.getAttribute("name");
				assert str != null && str.equals("") == false : Util.XMLToString(tag);
				per.addParam("name", str);
				
				percepts.addPercept(per);
			}
		}
		
	}
	
	
	public void checkPerceptSimEnd(Document doc)
	{
			String str;
			Percepts per;
			Parameter param;
			
			Element root = doc.getDocumentElement();
			assert root != null;
			assert root.getAttribute("type").equalsIgnoreCase("sim-end");

			Element simResult = (Element)root.getElementsByTagName("sim-result").item(0);
			assert simResult.getNodeName().equalsIgnoreCase("sim-result");
			
			str = simResult.getAttribute("ranking");
			assert str != null && str.equals("") == false;
			per = new Percepts("ranking");
			param = new Parameter<String>("val",str);
			per.addParam(param);
			
			str = simResult.getAttribute("score");
			assert str != null && str.equals("") == false;
			per = new Percepts("score");
			param = new Parameter<String>("val",str);
			per.addParam(param);

	}

}
